#include "fs.h"
#include "inode.h"
#include "super.h"

/*===========================================================================*
 *				fs_nfrags				     *
 *===========================================================================*/
PUBLIC int fs_nfrags (void) {
  struct inode * ino;
  int scale, zonesz, n;
  block_t blk, myblk;                            /* current block */
  off_t offset;

  /* Get Inode */
  ino = find_inode(fs_m_in.REQ_DEV, fs_m_in.REQ_INODE_NR);
  if(!ino) {
      panic("fs_nfrags failed - inode not found");
  }

  /* Is the file empty? */
  if(ino->i_size == 0) {
      /* Yes! Piece of cake: */
      fs_m_out.RES_NFRAGS = 0;
      return(OK);
  }

  /* Get first block and incrementer */
  scale = ino->i_sp->s_log_zone_size;         /* for block-zone conversion */
  zonesz = ino->i_sp->s_block_size << scale;  /* Size of a zone (incrementer)*/

  if( ino->i_sp->s_version == V1 ) {
      blk = conv2( ino->i_sp->s_native, (int)  ino->i_zone[0] << scale );
  }
  else if (ino->i_sp->s_version == V2 || ino->i_sp->s_version == V3) {
      blk = conv4( ino->i_sp->s_native, (long) ino->i_zone[0] << scale );
  }
  else {
      panic("unknown superblock version");
  }

  /* Count the number of fragments: */
  n=1; offset=0;
  while(offset < ino->i_size) {
      if( (myblk = read_map(ino, offset)) != blk) { /* is blk the next block?*/
          n += 1;                       /* No : discontiguous block */
          blk = myblk;
      }
      blk += 1 << scale;  /* get the block directly after this one */
      offset += zonesz;
  }

  /* Reply message : */
  fs_m_out.RES_NFRAGS = n;

  return(OK);
}
